package com.gitee.llj.shiro.config.shiro;

import com.alibaba.fastjson.JSONObject;
import com.gitee.llj.tools.base.ResultModel;
import com.gitee.llj.tools.exception.IncorrectCaptchaException;
import com.gitee.llj.tools.exception.NormalException;
import com.gitee.llj.tools.utils.FastJsonUtils;
import com.google.code.kaptcha.Constants;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * <p>自定义Filter</p>
 *
 * @Author llj
 * @Date 2018/5/11
 */
public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter{

    private static final String ALLOW_ORIGIN="http://localhost:8081";
    public static final String DEFAULT_CAPTCHA_PARAM = "kaptcha";

    private String captchaParam = DEFAULT_CAPTCHA_PARAM;

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse resp= (HttpServletResponse) response;
        resp.setHeader("Access-Control-Allow-Origin", ALLOW_ORIGIN);
        resp.setHeader("Access-Control-Allow-Credentials","true");
        if(this.isLoginRequest(request, response)) {
            if(this.isLoginSubmission(request, resp)) {
                return this.executeLogin(request, resp);
            } else {
                return true;
            }
        } else {
            resp.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            resp.setHeader("Access-Control-Max-Age", "3600");//30 min
            resp.addHeader("Access-Control-Allow-Headers", "x-requested-with,Content-Type");
            String header = ((HttpServletRequest) request).getHeader("Content-Type");
            if(header != null && header.equals("application/x-www-form-urlencoded")){
                resp.setCharacterEncoding("UTF-8");
                PrintWriter out = resp.getWriter();
                JSONObject jsonObject=new JSONObject();
                jsonObject.put("isTimeOut",true);

                out.print(FastJsonUtils.toJSONString(ResultModel.ok(jsonObject)));
                out.flush();
                out.close();
                return false;
            }else{
                this.saveRequestAndRedirectToLogin(request, response);
            }
            return false;
        }
    }
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

        CaptchaUsernamePasswordToken token = createToken(request, response);
        try {
            doCaptchaValidate((HttpServletRequest) request, token);
            Subject subject = getSubject(request, response);
            subject.login(token);
            return onLoginSuccess(token, subject, request, response);
        }catch (AuthenticationException e) {
            return onLoginFailure(token,e,request,response);
        }
    }
    //验证码jiao校验
    protected void doCaptchaValidate(HttpServletRequest request, CaptchaUsernamePasswordToken token){
        // 从session中获取图形吗字符串
        String captcha = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        // 校验
        if (captcha == null || !captcha.equals(token.getCaptcha())) {
            throw new NormalException("验证码输入有误");
        }
    }

    @Override
    protected CaptchaUsernamePasswordToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);
        String password = getPassword(request);
        String host = getHost(request);
        boolean rememberMe = isRememberMe(request);
        String captcha = getCaptcha(request);
        return new CaptchaUsernamePasswordToken(username,password.toCharArray(),rememberMe,host,captcha);
    }


    //保存异常对象到request
    @Override
    protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
        request.setAttribute(getFailureKeyAttribute(), ae);
    }
    protected  String getCaptcha(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }

    public String getCaptchaParam() {
        return captchaParam;
    }

    public void setCaptchaParam(String captchaParam) {
        this.captchaParam = captchaParam;
    }
}
